<?php
// @formatter:off
/**
 * @file WCDBItem.abs.php
 * @author Alejandro Dario Simi
 * @date $Date: 2013-05-24 23:14:00 +0000 (Fri, 24 May 2013) $
 *
 * $Id: WCDBItem.abs.php 66 2013-05-24 23:14:00Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/tags/wcomix-1.0.0.1/includes/db/WCDBItem.abs.php $
 */
// @formatter:on

/**
 * @class WCDBItem
 * This class represents a generic database object like a object table or an
 * index.
 */
abstract class WCDBItem {
	/**
	 * @var WCConnection Point to the database connection singleton.
	 */
	protected $_db = null;
	/**
	 * @var string Tables prefixes.
	 */
	protected $_dbprefix = "";
	/**
	 * @var boolean This flag indicates if an object exists or not in the
	 * database.
	 * It may hold three different values:
	 *	- true: The object exists.
	 *	- false: The object doesn't exist.
	 *	- null: The existence hasn't been checked yet.
	 */
	protected $_exists = null;
	/**
	 * @var string This is a full path relative to the wcomix root directory. It
	 * has to be a valid XML file containing the specification of a database
	 * object.
	 */
	protected $_filename = false;
	/**
	 * @var boolean This flag indicates if a XML file was already loaded and
	 * parsed successfully.
	 */
	protected $_loaded = false;
	/**
	 * @var string This property holds the name of the represented database
	 * object.
	 */
	protected $_name = false;
	/**
	 * @var SimpleXMLElement This is the root object for the XML file loaded
	 * and parsed.
	 */
	protected $_xml = false;
	/**
	 * Class basic constructor.
	 *
	 * @param string By default, it requires the same parameters than method
	 * load().
	 */
	public function __construct($filename) {
		//
		// Loading global pointers.
		global $wcDatabaseAccess;
		//
		// Building a shortcut for database connection singleton.
		$this->_db = WCConnection::Instance();
		//
		// Building a shortcut for database tables's prefix.
		$this->_dbprefix = $wcDatabaseAccess["prefix"];
		//
		// Loading specified file.
		$this->load($filename);
	}
	/**
	 * Class basic destructor.
	 */
	public function __destruct() {
		//
		// This class has nothing to clean before deleting.
	}
	//
	// Public methods.
	/**
	 * @abstract
	 * This method is the one in charge to perform any needed action to verify
	 * if a represented database object is as it's specified by the XML file.
	 *
	 * @param multitype $info This object will contain entries for each issue
	 * found while checking. It's contents and structure may differ on each
	 * inherited class and represented object, therefore, check child classes.
	 * @return boolean Returns true when it is as it has to be.
	 */
	public function check(&$info = null) {
		if($info !== null) {
			$info = null;
		}
		return false;
	}
	/**
	 * @abstract
	 * This method is the one in charge to perform any needed action to verify
	 * the existence of the represented object in the database.
	 *
	 * @return boolean Returns true when the represented database object
	 * exists.
	 */
	public function checkExistence() {
		return false;
	}
	/**
	 * @abstract
	 * When the object is checked and it's no as specified in the database,
	 * this method may be called to generate all those queries needed to alter
	 * the database and leave the represented database object as it has to be
	 * based on the loaded XML file.
	 *
	 * @return string[] Returns a list of queries to adapt the database. When
	 * it's not yet loaded, it returns false.
	 */
	public function ddlQueries() {
		return $this->loaded() ? array() : false;
	}
	/**
	 * This method allows to know if the represented database object exists or
	 * not.
	 *
	 * @return boolean Returns true when the object exists.
	 */
	public function exists() {
		//
		// Checking that the object is loaded and the existence is not yet
		// checked.
		if($this->loaded() && $this->_exists === null) {
			//
			// Checking the existence.
			$this->checkExistence();
		}
		//
		// Returning it's status.
		return $this->_exists;
	}
	/**
	 * This method allows to load this object with a XML file.
	 *
	 * @param string $filename Full path relative to wcomix root directory.
	 * @return boolean Returns true when the XML file was loaded successfully.
	 */
	public function load($filename) {
		//
		// Loading global pointers.
		global $wcROOTDIR;
		//
		// Setting default values.
		$this->_loaded = false;
		$this->_filename = false;
		//
		// Building the system full path to the XML file.
		$path = "{$wcROOTDIR}{$filename}";
		//
		// Checking if it exists and is valid against its DTD specification.
		if($filename && is_readable($path) && WCDBItem::Validate($path)) {
			//
			// Loading XML file as an objecct easy-to-use.
			$this->_xml = new SimpleXMLElement(file_get_contents($path));
			//
			// Since every node must have a name field, it is taken
			// as value for the property _name.
			$this->_name = "{$this->_xml->name}";
			//
			// At this point, everything was ok, therefore loading
			// status result is true.
			$this->_loaded = true;
			//
			// Saving file name.
			$this->_filename = $filename;
		} elseif(!is_readable($path)) {
			//
			// If the XML file is not readable, it is a fatal error.
			trigger_error(__CLASS__."::".__FUNCTION__."(): Unable to read '{$path}'", E_USER_ERROR);
		} elseif(!WCDBItem::Validate($path)) {
			//
			// If the XML file does not agree with its DTD, it won't
			// be possible to use it.
			trigger_error(__CLASS__."::".__FUNCTION__."(): XML '{$filename}' is not valid", E_USER_ERROR);
		} elseif(!$filename) {
			//
			// If no name was specified, well, there is a problem.
			trigger_error(__CLASS__."::".__FUNCTION__."(): Empty file name", E_USER_ERROR);
		}
		//
		// Returning the loading status result.
		return $this->_loaded;
	}
	/**
	 * This method allows to know if this object is loaded with some XML file.
	 *
	 * @return boolean Return true when it successfully loaded.
	 */
	public function loaded() {
		return $this->_loaded;
	}
	/**
	 * This method allows to know the name of the loaded object.
	 *
	 * @return string Returns a name or false when it's not loaded yet.
	 */
	public function name() {
		return $this->loaded() ? $this->_name : false;
	}
	//
	// Public class methods.
	/**
	 * This method allows to know if an XML file is valid against it's own DTD
	 * specification.
	 *
	 * @param string $path System full path for the XML file to be checked.
	 * @return boolean Returns true when it is valid.
	 */
	public static function Validate($path) {
		//
		// Setting the default value to be returned.
		$ok = false;
		//
		// Checking if the file exists and it's readable.
		if(is_readable($path)) {
			//
			// Creating a DOM as XML checker.
			$dom = new DOMDocument;
			//
			// Loading file into the DOM checker object.
			$dom->Load($path);
			//
			// Checking its validity.
			$ok = $dom->validate();
			//
			// Clearing DOM checker object.
			unset($dom);
		}
		//
		// Returning results.
		return $ok;
	}
}
?>
